package test.bhagya;

import com.googlecode.javacpp.Loader;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.googlecode.javacv.*;
import java.util.Vector;
import static com.googlecode.javacv.cpp.opencv_core.*;
//import static com.googlecode.javacv.cpp.opencv_imgproc.*;


public class CameraSkin implements Runnable {

    final int CAMERANO;
    CanvasFrame canvas = new CanvasFrame("Web Cam Live");
    CanvasFrame canvas1 = new CanvasFrame("HSV Skin");
    CanvasFrame canvas2 = new CanvasFrame("YCrCb Skin");
    CanvasFrame canvas3 = new CanvasFrame("Contours");

    CvScalar rgba_min = cvScalar(124, 133, 18, 0);
    CvScalar rgba_max = cvScalar(184, 193, 80, 0);

    CvScalar hsv_min = cvScalar(0, 45, 0, 0);
    CvScalar hsv_max = cvScalar(20, 255, 255, 0);

    CvScalar ycc_min = cvScalar(0, 131, 80, 0);
    CvScalar ycc_max = cvScalar(255, 185, 135, 0);
    //AdaptiveSkinDetector2 adapSkin=new AdaptiveSkinDetector(1,2):
    Robot robot;
    CvMemStorage storage = CvMemStorage.create();
    CvMemStorage storage1 = CvMemStorage.create();

    CvSeq hull;
    CvSeq fileredHull;
    CvSeq defects;


    public CameraSkin(int cameraNo) {
        super();
        this.CAMERANO = cameraNo;
        canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        try {
            robot = new Robot();
        } catch (AWTException ex) {
            Logger.getLogger(CameraSkin.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        FrameGrabber grabber = new VideoInputFrameGrabber(CAMERANO);
        try {
            grabber.start();
            Thread.sleep(1000);
            IplImage img;
            while (true) {
                img = grabber.grab();

                if (img != null) {
                    // show image on window
                    //cvFlip(img, img, 1);// l-r = 90_degrees_steps_anti_clockwise
                    canvas.showImage(img);

                    //IplImage hsvSkin = getHSVSkin(img);
                    //canvas1.showImage(hsvSkin);

                    IplImage yccSkin = getYCrCbSkin(img);
                    extractContours(yccSkin,img);
                    //drawAndComputeDefects(img);
                    canvas3.showImage(img);

                    //IplImage rgbSkin = getYCrCbSkin(img);
                    //canvas2.showImage(rgbSkin);

                }

            }
        } catch (Exception e) {
        }

    }

    private IplImage getThresholdImage(IplImage orgImg) {
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);
        cvInRangeS(orgImg, rgba_min, rgba_max, imgThreshold);
        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 15);
        return imgThreshold;


    }

    private IplImage getHSVSkin(IplImage orgImg){
        IplImage imgHSV = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgHSV, CV_BGR2HSV);
        cvInRangeS(imgHSV, hsv_min, hsv_max, imgThreshold);

        IplConvKernel rect_12 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvErode(imgThreshold, imgThreshold, rect_12, 1);

        IplConvKernel rect_6 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvDilate(imgThreshold, imgThreshold, null, 1);

        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 5);

        return imgThreshold;


    }

    private IplImage getYCrCbSkin(IplImage orgImg) {
        IplImage imgYCC = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgYCC, CV_BGR2YCrCb);
        cvInRangeS(imgYCC, ycc_min, ycc_max, imgThreshold);
        //cvDilate(imgThreshold, imgThreshold, null, 1);
        //cvErode(imgThreshold, imgThreshold, null, 1);

        IplConvKernel rect_12 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvErode(imgThreshold, imgThreshold, rect_12, 1);

        IplConvKernel rect_6 = cvCreateStructuringElementEx(6, 6, 2, 2, CV_SHAPE_RECT, null);
        cvDilate(imgThreshold, imgThreshold, null, 1);

        cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 5);
        return imgThreshold;


    }

    private IplImage getRGBSkin(IplImage orgImg) {
        IplImage imgHSV = cvCreateImage(cvGetSize(orgImg), 8, 3);
        IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);

        cvCvtColor(orgImg, imgHSV, CV_BGR2YCrCb);
        cvInRangeS(imgHSV, ycc_min, ycc_max, imgThreshold);
        //cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 15);
        return imgThreshold;

    }

    private void extractContours(IplImage skin,IplImage img){
        double result1 =0;
        double result2 =0;
        CvSeq largestcontour = new CvSeq(null);
        CvSeq contours = new CvSeq(null);

        cvFindContours(skin, storage, contours, Loader.sizeof(CvContour.class),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
        while(contours != null){
           result1 = contours.total();
           if(result1>result2){
               result2=result1;
               largestcontour = contours;
           }
        contours = contours.h_next();
        }
            if(largestcontour !=null){

             cvDrawContours(img,largestcontour, CvScalar.MAGENTA, CvScalar.WHITE, -1, 1, CV_FLOODFILL_MASK_ONLY);

             hull=cvConvexHull2(largestcontour, storage, CV_COUNTER_CLOCKWISE,0);
//             for(int i=0;i<largestcontour.total();i++){
//
//            CvPoint v=new CvPoint(cvGetSeqElem(largestcontour, i));
//            cvDrawCircle(img, v, 5, CvScalar.BLUE, -1, 8, 0);
//            System.out.println(" X value = "+v.x()+" ; Y value ="+v.y());
//            }

            System.out.println("elements="+hull.delta_elems());
            //hull =cvApproxPoly(hull, Loader.sizeof(CvContour.class), cvCreateMemStorage(0), CV_POLY_APPROX_DP, cvContourPerimeter(hull)*0.02, 0);
            defects = cvConvexityDefects(largestcontour,hull,storage);
            for(int i=0;i<hull.total();i++){

            CvPoint v=new CvPoint(cvGetSeqElem(hull, i));
            cvDrawCircle(img, v, 5, CvScalar.BLUE, -1, 8, 0);
            System.out.println(" X value = "+v.x()+" ; Y value ="+v.y());
        }

    }

    //private void convexHull(IplImage img){
    //}

//    private void drawAndComputeDefects(IplImage img){
//        for(int i=0;i<hull.total();i++){
//
//            CvPoint v=new CvPoint(cvGetSeqElem(hull, i));
//            cvDrawCircle(img, v, 5, CvScalar.BLUE, -1, 8, 0);
//            System.out.println(" X value = "+v.x()+" ; Y value ="+v.y());
//        }

        }





    }
